/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
var mongodb = require('mongodb');
var client = {};
//host:port/db,返回DB对象
function conn($config, callback) {
    var key = $.md5($config);
    var $delay  = 10;
    var $maxnum = 100;

    var delay = function(){ //等待数据库连接
        if(typeof client[key] === 'object'){
            callback(false, client[key]);
        }
        else if($maxnum<1){
            callback('mongo_connect_failure');
        }
        else {
            $maxnum --;
            setTimeout(delay, $delay);
        }
    }

    if (!client[key]){
        var url = "mongodb://" + $config;
        client[key] = 'connecting';
        mongodb.MongoClient.connect(url, function (err, db) {
            if(err){
                console.log(err.message);
                callback(err, db);
            }
            else{
                console.log('mongo[' + $config + '] connection success');
                client[key] = db;
                callback(false, db);
            }
        });
    }
    else if(typeof client[key] !== 'object'){
        delay();
    }
    else{
        callback(false, client[key]);
    }
}
exports.conn = conn;

function coll($config, $db, $coll, callback) {
    var config = $config+'/'+$db;
    conn(config, function (err, db) {
        if (err) {
            return callback(err, db);
        } else {
            var coll = db.collection($coll);
            coll['get'] = get;
            coll['set'] = set;
            coll['del'] = del;
            coll['add'] = add;
            coll['incr'] = incr;
            coll['page'] = page;
            coll['close'] = db.close;
            return callback(false, coll);
        }
    });
}

exports.coll = coll;


function add(info,option,callback) {
    if(!option){
        option = {};
    }
    this.insert(info, option,callback);
}
;


function get(query,option,callback) {
    if(typeof option === 'function'){
        callback = option;
        option = {};
    }
    if(!option){
        option = {};
    }
    option["multi"] = option["multi"] || false;
    if(!option['fields']){
        option['fields'] = {};
    }
    var dataType = option['dataType'] || 'json';
    if(option["multi"]){
        this.find(query, option, function(err,$cursor){
            if(err){
                return callback(err,$cursor);
            }
            if(dataType=='json'){
                return getObj($cursor,callback);
            }
            else{
                return getArr($cursor,callback);
            }
        });
    }
    else{
        this.findOne(query, option, callback);
    }
}
;

function set(query,info, option,callback) {
    if(typeof options === 'function'){
        callback = options;
        options = {};
    }
    else if(!callback){
        callback = function(){};
    }
    if(!option){
        option = {};
    }
    if(typeof(option["upsert"])==='undefined'){
        option["upsert"] = false;
    }
    if(typeof(option["multi"])==='undefined'){
        option["multi"] = false;
    }
    var update = {"$set":info};
    this.update(query,update, option, callback);
}
;

function del(query,option,callback) {
    if(!option){
        option = {};
    }
    if(typeof(option["single"])==='undefined'){
        option["single"] = true;
    }
    this.remove(query, option, callback);
}
;

function incr(query,info,option,callback) {
    if(!option){
        option = {};
    }
    option['upsert'] = true;
    option['new'] = true;
    var update = {"$inc":info};
    var sort = option['sort'] || [];
    this.findAndModify(query,sort, update,option, callback);
}


//分页显示
function page($query, $page, $size, $sort, $option,callback){
    var option = {};
    if(typeof $option==='function'){
        callback = $option;
    }
    else{
        option = $option;
    }
    $size = $size || 10;
    if($page<1){
        $page = 1;
    }
    option['multi'] = true;
    option['limit'] = $size;
    option['skip']  = ($page - 1 ) * $size;
    option['sort'] = $sort;
    if(!option['fields']){
        option['fields'] = {};
    }
    var dataType = option['dataType'] || 'array';
    var rows = {"page":$page,"size":$size,"total":0,"rows":[]};
    var $conn = this;
    var result = function(err,data){
        if(err){
            return callback(err,data);
        }
        rows['rows'] = data;
        return callback(false,rows);
    }
    var find = function(){
        $conn.find($query, option, function(err,$cursor){
            if(err){
                return callback(err,$cursor);
            }
            if(dataType=='json'){
                return getObj($cursor,result);
            }
            else{
                return getArr($cursor,result);
            }
        });
    }
    var count = function() {
        $conn.count($query, function (err, num) {
            if (err) {
                return callback(err, num);
            }
            if (num < 1) {
                return callback(false, rows);
            }
            rows['total'] = num;
            find();
        });
    }
    count();
}


var getArr = function($cursor,callback){
    $cursor.toArray(function(err,arr){
        if(err){
            return callback(err,arr);
        }
        return callback(false,arr);
    });
}

var getObj = function($cursor,callback){
    var rows = {};
    $cursor.each(function(err,item){
        if(err){
            return callback(err,item);
        }
        else if(item===null){
            return callback(false,rows);
        }
        else{
            var id = item['_id']||'';
            rows[id] = item;
        }
    });
}